package ru.ibrae.excelparser1.mainlogics.fileworkers;

import jxl.Cell;
import jxl.LabelCell;
import jxl.Workbook;

import jxl.biff.EmptyCell;

import jxl.write.*;
import jxl.write.Label;
import jxl.write.Number;

import ru.ibrae.excelparser1.excelstorageentities.FileNameInfo;
import ru.ibrae.excelparser1.excelstorageentities.entities.CommonInfo;
import ru.ibrae.excelparser1.excelstorageentities.entities.ExcelField;
import ru.ibrae.excelparser1.excelstorageentities.entities.ExcelFile;
import ru.ibrae.excelparser1.excelstorageentities.entities.InfoSheetHeader;
import ru.ibrae.excelparser1.excelstorageentities.entities.MyExcelCell;
import ru.ibrae.excelparser1.excelstorageentities.enumerations.DocumentType;
import ru.ibrae.excelparser1.excelstorageentities.enumerations.Mark;
import ru.ibrae.excelparser1.gui.Main;
import ru.ibrae.excelparser1.mainlogics.config.ConfigurationWorker;

import java.awt.*;

import java.io.File;
import java.io.IOException;

import java.text.SimpleDateFormat;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 * @author murr
 */
public class FileToFixCreator {
    //~ Static fields/initializers ---------------------------------------------

    static File file;

    //~ Methods ----------------------------------------------------------------
    public static String create(ExcelFile fileWithIncorrectInfo,
            FileNameInfo info) {
        try {
            String newIteration = info.getIteration() == null ? "01" : iterate(info.getIteration());
            SimpleDateFormat fileNamingFormat = new SimpleDateFormat(
                    "yy-MM-dd");

            file = createFile(fileWithIncorrectInfo,
                    fileNamingFormat,
                    newIteration);

            final String fileName = ConfigurationWorker.readConfiguration().getConfigFilePath()
                    + File.separator + file.getName();
            file = new File(fileName);

            if (!file.exists()) {
                file.createNewFile();
            } else {
                chooseFile(file);
            }

            WritableWorkbook workbook = Workbook.createWorkbook(file);
            WritableSheet sheet1 = workbook.createSheet("Лист 1", 0);
            WritableSheet sheet2 = workbook.createSheet("Лист 2", 1);
            fillSheet2(sheet2,
                    fileWithIncorrectInfo.getInfoSheetHeader(),
                    fileWithIncorrectInfo.getRows(),
                    fileWithIncorrectInfo.getFinallyBrokenRows());
            fillSheet1(sheet1, sheet2, fileWithIncorrectInfo.getCommonInfo());
            workbook.write();
            workbook.close();

            return file.getName();
        }
        catch (WriteException ex) {
            Logger.getLogger(FileToFixCreator.class.getName()).log(Level.SEVERE,
                    null,
                    ex);
        }
        catch (IOException ex) {
            Logger.getLogger(FileToFixCreator.class.getName()).log(Level.SEVERE,
                    null,
                    ex);
        }

        return null;
    }

    private static void chooseFile(File file)
            throws HeadlessException, IOException {
        if (JOptionPane.showConfirmDialog(null,
                "Файл уже существует, заменить?",
                "Файл уже существует",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.QUESTION_MESSAGE) == JOptionPane.NO_OPTION) {
            JFileChooser jFileChooser = new JFileChooser();
            jFileChooser.setSelectedFile(file);
            jFileChooser.setFileFilter(
                    new FileNameExtensionFilter("Файлы MS Excel 97-2003", "xls"));

            int ii = jFileChooser.showSaveDialog(jFileChooser);

            if (ii == JFileChooser.APPROVE_OPTION) {
                jFileChooser.getSelectedFile().createNewFile();
            } else {
                chooseFile(file);
            }
        } else {
            file.createNewFile();
        }
    }

    private static File createFile(ExcelFile fileWithIncorrectInfo,
            SimpleDateFormat fileNamingFormat,
            String iteration) {
        File tempFile;

        if (Main.sort()) {
            File dir = new File(fileWithIncorrectInfo.getCommonInfo().getOgrn());

            if (!dir.exists()) {
                boolean created = dir.mkdir();
            }

            String path = dir + File.separator
                    + fileNamingFormat.format(
                    fileWithIncorrectInfo.getCommonInfo().getBeginning()) + "_"
                    + fileNamingFormat.format(
                    fileWithIncorrectInfo.getCommonInfo().getEnd()) + "_"
                    + iteration + ".xls";
            tempFile = new File(path);
        } else {
            tempFile = new File(
                    fileWithIncorrectInfo.getCommonInfo().getOgrn() + "_"
                    + fileNamingFormat.format(
                    fileWithIncorrectInfo.getCommonInfo().getBeginning())
                    + "_"
                    + fileNamingFormat.format(
                    fileWithIncorrectInfo.getCommonInfo().getEnd()) + "_"
                    + iteration + ".xls");
        }

        return tempFile;
    }

    /**
     *
     * @param sheet Лист 1
     * @param sheet1 Лист 2
     * @param commonInfo
     * @throws WriteException
     */
    private static void fillSheet1(WritableSheet sheet, WritableSheet sheet1,
            CommonInfo commonInfo)
            throws WriteException {
        ArrayList<MyExcelCell> correctList1Sctructure = ConfigurationWorker.getCorrectList1Sctructure();

        for (MyExcelCell myExcelCell : correctList1Sctructure) {
            String cellType = myExcelCell.getCellType();
            int col = myExcelCell.getCol();
            int row = myExcelCell.getRow();
            String content = myExcelCell.getContent();
            WritableCell wc = null;

            if (col == 0) {
                if (cellType.equalsIgnoreCase("label")) {
                    wc = new Label(col, row, content);
                } else if (cellType.equalsIgnoreCase("empty")) {
                    wc = new EmptyCell(col, row);
                }
            } else {
                if (row != 10) {
                    wc = getFilledWritableCell(row, commonInfo, cellType);
                } else {
                    wc = new Number(col, row, sheet1.getRows() - 2);
                }
            }

            sheet.addCell(wc);
        }
    }

    private static void fillSheet2(WritableSheet sheet2,
            InfoSheetHeader infoSheetHeader,
            LinkedList<ExcelField> rows,
            ArrayList<Cell[]> cells)
            throws WriteException {
        for (Cell cell : infoSheetHeader.getCells()) {
            if (cell instanceof LabelCell) {
                LabelCell labelCell = (LabelCell) cell;
                WritableCellFormat cellFormat = new WritableCellFormat(
                        labelCell.getCellFormat());
                Label l = new Label(labelCell);
                l.setCellFormat(cellFormat);

                sheet2.addCell(l);
            }
        }

        sheet2.mergeCells(0, 0, 0, 1);
        sheet2.mergeCells(1, 0, 2, 0);
        sheet2.mergeCells(3, 0, 7, 0);
        sheet2.mergeCells(8, 0, 12, 0);
        sheet2.mergeCells(13, 0, 16, 0);
        sheet2.mergeCells(17, 0, 20, 0);

        int currentRow = 2;

        if (rows != null && !rows.isEmpty()) {
            for (ExcelField excelField : rows) {
                WritableCell writableCell[] = new WritableCell[21];
                writableCell[0] = new Number(0, currentRow, currentRow - 1);
                writableCell[1] = new Label(1,
                        currentRow,
                        excelField.getMchsLetter().getNumber());
                writableCell[2] = new DateTime(2,
                        currentRow,
                        excelField.getMchsLetter().getDate());

                String oldSecondName = excelField.getMchsLetter().getPerson().getOldSecondName();

                if (oldSecondName != null) {
                    oldSecondName = " (" + oldSecondName + ")";
                } else {
                    oldSecondName = "";
                }

                writableCell[3] = new Label(3,
                        currentRow,
                        excelField.getMchsLetter().getPerson().getSecondName()
                        + oldSecondName);

                String firstName = excelField.getMchsLetter().getPerson().getFirstName();
                String oldFirstName = excelField.getMchsLetter().getPerson().getOldFirstName();
                String names = firstName;

                if (oldFirstName != null) {
                    names += ( " (" + oldFirstName + ")" );
                }

                writableCell[4] = ( firstName == null )
                        ? new EmptyCell(4, currentRow)
                        : new Label(4, currentRow, oldFirstName);

                String thirdName = excelField.getMchsLetter().getPerson().getThirdName();
                String oldThirdName = excelField.getMchsLetter().getPerson().getOldThirdName();
                names = thirdName;

                if (oldThirdName != null) {
                    names += ( " (" + oldThirdName + ")" );
                }

                writableCell[5] = ( thirdName == null )
                        ? new EmptyCell(5, currentRow)
                        : new Label(5, currentRow, names);

                Date birthDate = excelField.getMchsLetter().getPerson().getBirthDate();
                writableCell[6] = ( birthDate == null )
                        ? new EmptyCell(6, currentRow)
                        : new DateTime(6, currentRow, birthDate);

                String address = excelField.getMchsLetter().getPerson().getAddress();
                writableCell[7] = ( address == null ) ? new EmptyCell(7, currentRow)
                        : new Label(7, currentRow,
                        address);

                DocumentType documentType = excelField.getMchsLetter().getPerson().getDocumentInfo().getDocumentType();
                String toWrite = null;

                if (documentType != null) {
                    switch (documentType) {
                        case MILITARY_ID:
                            toWrite = "В";

                            break;

                        case PASSPORT:
                            toWrite = "П";

                            break;

                        case TEMP_CERTIFICATE:
                            toWrite = "У";

                            break;

                        default:
                            toWrite = null;
                    }
                }

                writableCell[8] = ( documentType == null )
                        ? new EmptyCell(8, currentRow)
                        : new Label(8, currentRow, toWrite);

                String series = excelField.getMchsLetter().getPerson().getDocumentInfo().getSeries();
                writableCell[9] = ( series == null ) ? new EmptyCell(9, currentRow)
                        : new Label(9, currentRow, series);

                String number = excelField.getMchsLetter().getPerson().getDocumentInfo().getNumber();
                writableCell[10] = ( number == null ) ? new EmptyCell(10, currentRow)
                        : new Label(10, currentRow,
                        number);

                Date whenGiven = excelField.getMchsLetter().getPerson().getDocumentInfo().getWhenGiven();
                writableCell[11] = ( whenGiven == null )
                        ? new EmptyCell(11, currentRow)
                        : new DateTime(11, currentRow, whenGiven);

                String whereGiven = excelField.getMchsLetter().getPerson().getDocumentInfo().getWhereGiven();
                writableCell[12] = ( whereGiven == null )
                        ? new EmptyCell(12, currentRow)
                        : new Label(12, currentRow, whereGiven);
                writableCell[13] = new Label(
                        13,
                        currentRow,
                        excelField.getMchsLetter().getPerson().getCurrentCertificate().getSeries());
                writableCell[14] = new Label(
                        14,
                        currentRow,
                        excelField.getMchsLetter().getPerson().getCurrentCertificate().getNumber());

                writableCell[15] = new DateTime(
                        15,
                        currentRow,
                        excelField.getMchsLetter().getPerson().getCurrentCertificate().getWhenGiven());

                Mark status = excelField.getMchsLetter().getPerson().getCurrentCertificate().getStatus();

                switch (status) {
                    case D:
                        writableCell[16] = new Label(16, currentRow, "Д");

                        break;

                    case DP:
                        writableCell[16] = new Label(16, currentRow, "ДП");

                        break;

                    case NO_MARK:
                        writableCell[16] = new EmptyCell(16, currentRow);

                        break;

                    case P:
                        writableCell[16] = new Label(16, currentRow, "П");
                }

                String series1 = excelField.getMchsLetter().getPerson().getPreviousCertificate().getSeries();
                writableCell[17] = ( series1 == null )
                        ? new EmptyCell(17, currentRow)
                        : new Label(17, currentRow, series1);

                String number1 = excelField.getMchsLetter().getPerson().getPreviousCertificate().getNumber();
                writableCell[18] = ( number1 == null )
                        ? new EmptyCell(18, currentRow)
                        : new Label(18, currentRow, number1);

                Date whenGiven1 = excelField.getMchsLetter().getPerson().getPreviousCertificate().getWhenGiven();
                writableCell[19] = ( whenGiven == null )
                        ? new EmptyCell(19, currentRow)
                        : new DateTime(19, currentRow, whenGiven1);

                Mark status1 = excelField.getMchsLetter().getPerson().getPreviousCertificate().getStatus();

                switch (status1) {
                    case D:
                        writableCell[20] = new Label(20, currentRow, "Д");

                        break;

                    case DP:
                        writableCell[20] = new Label(20, currentRow, "ДП");

                        break;

                    case NO_MARK:
                        writableCell[20] = new EmptyCell(20, currentRow);

                        break;

                    case P:
                        writableCell[20] = new Label(20, currentRow, "П");
                }

                for (WritableCell writableC : writableCell) {
                    sheet2.addCell(writableC);
                }

                currentRow++;
            }
        }

        if (( cells != null ) && !cells.isEmpty()) {
            for (Cell cellRow[] : cells) {
                for (Cell cell : cellRow) {
                    WritableCell wc = new Label(cell.getColumn(),
                            currentRow,
                            cell.getContents());
                    if (cell.getCellFormat() != null) {
                        wc.setCellFormat(wc.getCellFormat());
                    }
                    try {
                        sheet2.addCell(wc);
                    }
                    catch (Throwable t) {
                        for (StackTraceElement stackTraceElement : t.getStackTrace()) {
                            System.err.println(stackTraceElement.toString());
                        }
                    }
                }

                currentRow++;
            }
        }
    }

    private static Object getCellContent(int row, CommonInfo commonInfo) {
        Object content = null;

        switch (row) {
            case 0:
                content = commonInfo.getFullName();

                break;

            case 1:
                content = commonInfo.getShortName();

                break;

            case 2:
                content = commonInfo.getOgrn();

                break;

            case 3:
                content = commonInfo.getOkato();

                break;

            case 6:
                content = commonInfo.getBeginning();

                break;

            case 7:
                content = commonInfo.getEnd();

                break;

            case 9:
                content = new Date();

                break;
        }

        return content;
    }

    /**
     * Возвращает итерацию для названия
     * @param Нынешняя итерация
     * @return
     */
    private static String iterate(Integer iteration) {
        Integer prevIter = Integer.valueOf(iteration);
        String newIteration = String.valueOf(prevIter + 1);

        return ( newIteration.length() == 2 ) ? newIteration : ( "0"
                + newIteration );
    }

    /**
     * returns filled writableCell
     * @param row Cell row
     * @param commonInfo CommonInfo
     * @param cellType CellType from saved XML
     * @return Filled WritableCell
     */
    private static WritableCell getFilledWritableCell(int row,
            CommonInfo commonInfo,
            String cellType) {
        WritableCell wc = null;
        Object content = null;
        content = getCellContent(row, commonInfo);

        if (cellType.equalsIgnoreCase("date")) {
            wc = new DateTime(1, row, (Date) content);
        } else if (cellType.equalsIgnoreCase("empty")) {
            wc = new Blank(1, row);
        } else {
            wc = new Label(1, row, content.toString());
        }

        return wc;
    }
}
